package appClientModule;

public class ReinforcementFeatureSet {
	public final int NUMFEATURES = 4;
	
	public double[] featureValues(Hand hand, Card[] pile, int pilelength, Card card) {
		double[] values = new double[NUMFEATURES];
		if (card != null && pilelength > 0) {
			
			// calculate each feature in its own method for cleanliness
			
			values[0] = getCardRank(pile, pilelength, hand, card);
			values[1] = hasValue(hand, 2);
			values[2] = hasValue(hand, 10);
			values[3] = isPileEmptyOrCardHigherThanTopCard(pile, pilelength, card);
			//values[4] = makesFourOfAKind(pile, pilelength, hand, card);
			//values[5] = isNormal(card); // bad
			//values[6] = isValue(card, 2); // bad
			//values[7] = isValue(card, 10); // bad
			
			// ideas:
			// - is card 2 or 10?
			// - is card equal to top card?
			// - difference in value between top card and card
			// - number of cards in hand of the same value as card
			// - if opponent to the left has the fewest cards of all opponents, rank cards with 2 lower than 3 and 10 lowest of all
			// - if opponent across has the fewest cards, rank cards with 10 lowest and 2 between 3 and 4
			// - if opponent to the right has the fewest cards, rank cards with 10 lowest and 2 between 3 and 4
		}
		return values;
	}
	
	/**
	 * Returns value of card, 2's are given a value higher than Aces and 10's
	 * are given the highest rank of all.
	 */
	private double getCardRank(Card[] pile, int pilelength, Hand hand, Card card) {
		if (card.getValue() == 2) {
			return 15.0;
		} else if (card.getValue() == 10) {
			return 16.0;
		}
		
		return card.getValue();
	}
	
	private double isPileEmptyOrCardHigherThanTopCard(Card[] pile, int pilelength, Card card) {
		if (pilelength == 0) {
			return 1.0;
		}
		
		Card top = pile[pilelength - 1];
		return card.getValue() > top.getValue() ? 1.0 : 0.0;
	}
	
	private double hasValue(Hand hand, int value) {
		for (int i = 0; i < hand.hand.length; i++) {
			Card card = hand.hand[i];
			if (card == null) {
				break;
			}
			
			if (card.getValue() == value) {
				return 1.0;
			}
		}
		
		return 0.0;
	}
	
	/**
	 * return 1.0 if playing card (and its duplicates) completes a four of a kind 
	 */
	private double makesFourOfAKind(Card[] pile, int pileLength, Hand hand, Card card) {
		int duplicates = 0;
		
		// count number of duplicates already on pile
		for (Card c : pile) {
			if (c == null || c.getValue() != card.getValue()) {
				break;
			}
			
			duplicates++;
		}
		
		// count number of duplicates played
		if (hand.length() > 1) {
			for (Card c : hand.hand) {
				if (c == null) {
					break;
				}
				
				if (c.getValue() == card.getValue()) {
					duplicates++;
				}
			}
		} else if (hand.isFaceUp()) {
			for (Card c : hand.faceup) {
				if (c != null && c.getValue() == card.getValue()) {
					duplicates++;
				}
			}
		} else {
			duplicates++;
		}
		
		return duplicates == 4 ? 1.0 : 0.0;
	}
	
	private double isValue(Card card, int value) {
		return card.getValue() == value ? 1.0 : 0.0;
	}
	
	private double isNormal(Card card) {
		if (card.getValue() == 2 || card.getValue() == 10) {
			return 0.0;
		}
		
		return 1.0;
	}
}
